﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AutoMapper;
using EasyMvcBlog.DTO;
using EasyMvcBlog.Data;
using EasyMvcBlog.Infrastructure.Repository.DataRepository;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Linq;
using Webdiyer.WebControls.Mvc;

namespace EasyMvcBlog.Domain
{
    public class ArticleDomain
    {
        private ArticleRepository articleRepository = new ArticleRepository();

        #region - 事件 -

        public delegate void ArticleDelegate(Article article);
        public event ArticleDelegate BeforeCreateArticle;
        public event ArticleDelegate AfterCreateArticle;
        public event ArticleDelegate BeforeUpdateArticle;
        public event ArticleDelegate AfterUpdateArticle;

        #endregion

        public ArticleDomain()
        {

        }

        /// <summary>
        /// 获得文章的分类统计信息
        /// </summary>
        /// <returns></returns>
        public List<ArticleCategoryDTO> ArticleCategoryStatistics()
        {
            using (ISession session = articleRepository.GetNhibernateSession())
            {
                //对文章按分类进行分组
                var list = session.Query<Article>().GroupBy(o => o.Category.Id)
                    .Select(p => new { CategoryId = p.Key, ArticleCount = p.Count() }).ToList();

                //和category表join查询
                return (from s in list
                        join c in session.Query<Category>() on s.CategoryId equals c.Id
                        select new ArticleCategoryDTO(c.CategoryName, s.ArticleCount)).ToList();
            }
        }

        public void CreateArticle(ArticleDTO articleDTO)
        {
            Mapper.CreateMap<ArticleDTO, Article>();
            Article article = Mapper.Map<ArticleDTO, Article>(articleDTO);

            if (BeforeCreateArticle != null)
            {
                BeforeCreateArticle(article);
            }

            articleRepository.Add(article);

            if (AfterCreateArticle != null)
            {
                AfterCreateArticle(article);
            }
        }

        /// <summary>
        /// 得到文章的分页结果，按发布时间倒序
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public PagedArticleDTO GetArticleByPage(int pageIndex, int pageSize)
        {
            PagedArticleDTO dto = new PagedArticleDTO();
            List<ArticleDTO> allArticles = GetAllArticles();

            dto.Articles = new PagedList<ArticleDTO>(allArticles, pageIndex, pageSize);
            dto.TotalCount = allArticles.Count;
            if (allArticles.Count % pageSize == 0)
            {
                dto.TotalPage = allArticles.Count / pageSize;
            }
            else
            {
                dto.TotalPage = allArticles.Count / pageSize + 1;
            }

            return dto;
        }

        public List<ArticleDTO> GetAllArticles()
        {
            IList<Article> articles = articleRepository.GetAll();
            Mapper.CreateMap<Article, ArticleDTO>();
            return Mapper.Map<IList<Article>, List<ArticleDTO>>(articles);
        }

        public ArticleDTO GetArticleDTO(int id)
        {
            Article article = articleRepository.GetById(id);
            Mapper.CreateMap<Article, ArticleDTO>();
            return Mapper.Map<Article, ArticleDTO>(article);
        }

        public Article GetArticle(int id)
        {
            return articleRepository.GetById(id);
        }

        public void UpdateArticle(ArticleDTO articleDTO)
        {
            Mapper.CreateMap<ArticleDTO, Article>();
            Article article = Mapper.Map<ArticleDTO, Article>(articleDTO);

            if (BeforeUpdateArticle != null)
            {
                BeforeUpdateArticle(article);
            }

            articleRepository.Update(article);

            if (AfterUpdateArticle != null)
            {
                AfterUpdateArticle(article);
            }
        }

        public void UpdateArticle(Article article)
        {
            if (BeforeUpdateArticle != null)
            {
                BeforeUpdateArticle(article);
            }

            articleRepository.Update(article);

            if (AfterUpdateArticle != null)
            {
                AfterUpdateArticle(article);
            }
        }

        public List<ArticleDTO> GetArticleByTag(int tagId)
        {
            using (ISession session = articleRepository.GetNhibernateSession())
            {
                TagRepository tagRepository = new TagRepository();
                Tag t = tagRepository.GetById(tagId);
                List<Article> articles = session.Query<Article>().Where(o => o.Tags.Contains(t)).ToList();
                Mapper.CreateMap<Article, ArticleDTO>();
                return Mapper.Map<List<Article>, List<ArticleDTO>>(articles);
            }
        }

        public List<ArticleDTO> GetArticleByCategory(int categoryId)
        {
            using (ISession session = articleRepository.GetNhibernateSession())
            {
                CategoryRepository categoryRepository = new CategoryRepository();
                Category c = categoryRepository.GetById(categoryId);
                List<Article> articles = session.Query<Article>().Where(o => o.Category == c).ToList();
                Mapper.CreateMap<Article, ArticleDTO>();
                return Mapper.Map<List<Article>, List<ArticleDTO>>(articles);
            }
        }

        /// <summary>
        /// 删除文章集合中所有包含某个tag文章的这个tag
        /// </summary>
        /// <param name="article"></param>
        /// <param name="tagId"></param>
        public void RemoveArticlesTag(List<Article> article, int tagId)
        {
            if (article == null || tagId < 0)
            {
                return;
            }

            using (ISession session = articleRepository.GetNhibernateSession())
            using (ITransaction transaction = session.BeginTransaction())
            {
                try
                {
                    Tag tag = session.Query<Tag>().Where(o => o.Id == tagId).FirstOrDefault();
                    if (tag != null && tag.Id > 0)
                    {
                        foreach (Article a in article)
                        {
                            a.Tags.Remove(tag);
                            session.Update(a);
                        }
                        transaction.Commit();
                    }
                }
                catch (Exception)
                {
                    transaction.Rollback();
                    throw;
                }
            }


        }

        public void RemoveArticlesTag(List<ArticleDTO> article, int tagId)
        {
            Mapper.CreateMap<ArticleDTO, Article>();
            List<Article> articleList = Mapper.Map<List<ArticleDTO>, List<Article>>(article);
            RemoveArticlesTag(articleList, tagId);
        }
    }
}
